home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / msh-156.lha / util / messyfmt.c < prev    next >
C/C++ Source or Header  |  1996-12-22  |  13KB  |  500 lines

  1. /*
  2.  * $Id: messyfmt.c,v 1.56 1996/12/22 00:22:33 Rhialto Rel $
  3.  * $Log: messyfmt.c,v $
  4.  * Revision 1.56  1996/12/22  00:22:33  Rhialto
  5.  * Cosmetics.
  6.  *
  7.  * Revision 1.55  1993/12/30  23:28:00  Rhialto
  8.  * Freeze for MAXON5.
  9.  *
  10.  * Revision 1.54  1993/06/24  05:35:45  Rhialto
  11.  * DICE 2.07.54R.
  12.  *
  13.  * Revision 1.53  92/10/25  02:45:24  Rhialto
  14.  * No real change.
  15.  *
  16.  * Revision 1.51  92/04/17  15:39:11  Rhialto
  17.  * Freeze for MAXON3.
  18.  *
  19.  * Revision 1.49  91/11/15  23:04:19  Rhialto
  20.  * Now suggest a reasonable FAT size when prompting
  21.  *
  22.  * Revision 1.48  91/11/03  00:50:10  Rhialto
  23.  * Add command line options ASK, QUICK and BOOT.
  24.  *
  25.  * Revision 1.46  91/10/06  18:25:23  Rhialto
  26.  *
  27.  * Freeze for MAXON
  28.  *
  29.  * Revision 1.42  91/06/14  00:06:25  Rhialto
  30.  * DICE conversion
  31.  *
  32.  * Revision 1.40  91/03/03  17:57:08  Rhialto
  33.  * Freeze for MAXON
  34.  *
  35.  * Revision 1.30  90/06/04  23:20:13  Rhialto
  36.  * Release 1 Patch 3
  37.  *
  38.  * MESSYFMT.C
  39.  *
  40.  * Formats a disk. Low-level formatting can also be done by mounting a file
  41.  * system and using the AmigaDOS format command.
  42.  *
  43.  * This code is (C) Copyright 1989-1991 by Olaf Seibert. All rights reserved.
  44.  * May not be used or copied without a licence.
  45.  */
  46.  
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <signal.h>
  51. #include "han.h"
  52.  
  53. const char    idString[] = "$\VER: MessyFmt $Revision: 1.56 $ $Date: 1996/12/22 00:22:33 $\r\n";
  54.  
  55. const ulong    BootBlock[] = {
  56.     0xEB349049, 0x424D2020, 0x332E3200, 0x02020100,    /* ...IBM  3.2..... */
  57.     0x027000A0, 0x05F90300, 0x09000200, 0x00000000,
  58.     0x00000000, 0x00000000, 0x00000000, 0x0000000F,
  59.     0x00000000, 0x0100FA33, 0xC08ED0BC, 0x007C1607,
  60.     0xBB780036, 0xC5371E56, 0x1653BF2B, 0x7CB90B00,
  61.     0xFCAC2680, 0x3D007403, 0x268A05AA, 0x8AC4E2F1,
  62.     0x061F8947, 0x02C7072B, 0x7CFBCD13, 0x7267A010,
  63.     0x7C98F726, 0x167C0306, 0x1C7C0306, 0x0E7CA33F,
  64.     0x7CA3377C, 0xB82000F7, 0x26117C8B, 0x1E0B7C03,
  65.     0xC348F7F3, 0x0106377C, 0xBB0005A1, 0x3F7CE896,
  66.     0x00B80102, 0xE8AA0072, 0x198BFBB9, 0x0B00BECD,
  67.     0x7DF3A675, 0x0D8D7F20, 0xBED87DB9, 0x0B00F3A6,
  68.     0x7418BE6E, 0x7DE86100, 0x32E4CD16, 0x5E1F8F04,
  69.     0x8F4402CD, 0x19BEB77D, 0xEBEBA11C, 0x0533D2F7,
  70.     0x360B7CFE, 0xC0A23C7C, 0xA1377CA3, 0x3D7CBB00,
  71.     0x07A1377C, 0xE84000A1, 0x187C2A06, 0x3B7C4050,
  72.     0xE84E0058, 0x72CF2806, 0x3C7C760C, 0x0106377C,
  73.     0xF7260B7C, 0x03D8EBD9, 0x8A2E157C, 0x8A16FD7D,
  74.     0x8B1E3D7C, 0xEA000070, 0x00AC0AC0, 0x7422B40E,
  75.     0xBB0700CD, 0x10EBF233, 0xD2F73618, 0x7CFEC288,
  76.     0x163B7C33, 0xD2F7361A, 0x7C88162A, 0x7CA3397C,
  77.     0xC3B4028B, 0x16397CB1, 0x06D2E60A, 0x363B7C8B,
  78.     0xCA86E98A, 0x16FD7D8A, 0x362A7CCD, 0x13C30D0A,
  79.     0x4E6F6E2D, 0x53797374, 0x656D2064, 0x69736B20,    /* Non-System disk  */
  80.     0x6F722064, 0x69736B20, 0x6572726F, 0x720D0A52,    /* or disk error..R */
  81.     0x65706C61, 0x63652061, 0x6E642073, 0x7472696B,    /* eplace and strik */
  82.     0x6520616E, 0x79206B65, 0x79207768, 0x656E2072,    /* e any key when r */
  83.     0x65616479, 0x0D0A000D, 0x0A446973, 0x6B20426F,    /* eady.....Disk Bo */
  84.     0x6F742066, 0x61696C75, 0x72650D0A, 0x0049424D,    /* ot failure...IBM */
  85.     0x42494F20, 0x20434F4D, 0x49424D44, 0x4F532020,    /* BIO    COMIBMDOS   */
  86.     0x434F4D00, 0x00000000, 0x00000000, 0x00000000,    /* COM............. */
  87.     0x00000000, 0x00000000, 0x00000000, 0x000055AA,
  88. };
  89.  
  90. byte           *DiskTrack;
  91. long        TrackSize;
  92. int        Track;
  93. int        EndTrack;
  94. word        nsides;
  95. struct IOExtTD *TDReq;
  96. char           *Device;
  97. sig_atomic_t    Break;
  98. int        Ask;
  99. int        Boot;
  100. int        Quick;
  101. int        Argc;
  102. char          **Argv;
  103. char           *Argv0;
  104.  
  105. int
  106. todigit(char   c)
  107. {
  108.     if ((c -= '0') < 0 || c > ('F' - '0'))
  109.     return 42;
  110.  
  111.     if (c >= ('A' - '0')) {
  112.     c -= 'A' - '9' - 1;
  113.     }
  114.     return c;
  115. }
  116.  
  117. long
  118. ntoi(char  *str)
  119. {
  120.     long        total = 0;
  121.     long        value;
  122.     int         digit;
  123.     int         base;
  124.  
  125.     /* First determine the base */
  126. number:
  127.     if (*str == '0') {
  128.     if (*++str == 'x') {    /* 0x means hexadecimal */
  129.         base = 16;
  130.         str++;
  131.     } else {
  132.         base = 8;        /* Otherwise, 0 means octal */
  133.     }
  134.     } else {
  135.     base = 10;        /* and any other digit means decimal */
  136.     }
  137.  
  138.     value = 0;
  139.     while ((digit = todigit(*str)) < base) {
  140.     value *= base;
  141.     value += digit;
  142.     str++;
  143.     }
  144.  
  145. suffix:
  146.     switch (*str++) {
  147.     case 'm':                   /* scale with megabytes */
  148.     value *= 1024L * 1024;
  149.     goto suffix;
  150.     case 'k':                   /* scale with kilobytes */
  151.     value *= 1024;
  152.     goto suffix;
  153.     case 's':                   /* scale with sectors */
  154.     value *= TD_SECTOR;    /* or maybe even kilosectors! */
  155.     goto suffix;
  156.     case 'b':                   /* scale with bytes */
  157.     goto suffix;
  158.     }
  159.     str--;
  160.  
  161.     total += value;
  162.  
  163.     if (*str >= '0' && *str <= '9')
  164.     goto number;        /* Allow 10k512, recursion eliminated */
  165.  
  166.     return total;
  167. }
  168.  
  169. word
  170. input(char *question, word defval)
  171. {
  172.     char        buf[80];
  173.  
  174.     if (!Ask)
  175.     return defval;
  176.  
  177.     printf("%s? [%d] ", question, defval);
  178.     fflush(stdout);
  179.     if (fgets(buf, sizeof (buf) - 1, stdin)) {
  180.     if (buf[0] && buf[0] != '\n')
  181.         defval = ntoi(buf);
  182.     }
  183.     return defval;
  184. }
  185.  
  186. void
  187. PutWord(byte *address, word value)
  188. {
  189.     address[0] = value;
  190.     address[1] = value >> 8;
  191. }
  192.  
  193. word
  194. SetWord(byte *address, char *question, word value)
  195. {
  196.     value = input(question, value);
  197.     PutWord(address, value);
  198.  
  199.     return value;
  200. }
  201.  
  202. byte
  203. SetByte(byte *address, char *question, word value)
  204. {
  205.     value = input(question, value);
  206.     return *address = value;
  207. }
  208.  
  209. byte           *
  210. MaybeWrite(byte *block)
  211. {
  212.     while (block >= (DiskTrack + TrackSize)) {
  213.     int        t,
  214.             s;
  215.  
  216.     t = Track / nsides;
  217.     s = Track % nsides;
  218.     printf("  Writing cylinder %3d side %d...\r", t, s);
  219.     fflush(stdout);
  220.     TDReq->iotd_Req.io_Command = TD_FORMAT;
  221.     TDReq->iotd_Req.io_Data = (APTR) DiskTrack;
  222.     TDReq->iotd_Req.io_Length = TrackSize;
  223.     TDReq->iotd_Req.io_Offset = TrackSize * Track;
  224.     DoIO((struct IORequest *)TDReq);
  225.     if (TDReq->iotd_Req.io_Error) {
  226.         printf(" Write error %d on cylinder %d side %d.\n",
  227.            TDReq->iotd_Req.io_Error, t, s);
  228.     }
  229.     TDReq->iotd_Req.io_Command = CMD_UPDATE;
  230.     DoIO((struct IORequest *)TDReq);
  231.     if (TDReq->iotd_Req.io_Error) {
  232.         printf("Update error %d on cylinder %d side %d.\n",
  233.            TDReq->iotd_Req.io_Error, t, s);
  234.     }
  235.     TDReq->iotd_Req.io_Command = CMD_CLEAR;
  236.     DoIO((struct IORequest *)TDReq);
  237.  
  238.     printf("  Read\r");
  239.     fflush(stdout);
  240.     TDReq->iotd_Req.io_Command = CMD_READ;
  241.     TDReq->iotd_Req.io_Data = (APTR) DiskTrack;
  242.     TDReq->iotd_Req.io_Length = TrackSize;
  243.     TDReq->iotd_Req.io_Offset = TrackSize * Track;
  244.     DoIO((struct IORequest *)TDReq);
  245.     if (TDReq->iotd_Req.io_Error) {
  246.         printf("  Read error %d on cylinder %d side %d.\n",
  247.            TDReq->iotd_Req.io_Error, t, s);
  248.     }
  249.     setmem(DiskTrack, (int) TrackSize, 0);
  250.     Track++;
  251.     if ((block -= TrackSize) < DiskTrack)
  252.         block = DiskTrack;
  253.     }
  254.     return block;
  255. }
  256.  
  257. void
  258. breakhandler(int signo)
  259. {
  260.     signal(signo, breakhandler);
  261.     Break = 1;
  262. }
  263.  
  264. void
  265. usage(void)
  266. {
  267.     printf("Usage: %s [ASK/BOOT/QUICK] <unitnr> [<device>]\n"
  268.        "Formats a messydos volume in any desired shape.\n",
  269.        Argv0);
  270.     exit(1);
  271. }
  272.  
  273. int
  274. argswitch(char *sw)
  275. {
  276.     if (Argc > 1 && stricmp(sw, Argv[1]) == 0) {
  277.     Argc--;
  278.     Argv++;
  279.     return 1;
  280.     }
  281.     return 0;
  282. }
  283.  
  284. int
  285. argnum(void)
  286. {
  287.     if ((Argc <= 1) || (Argv[1][0] < '0') || (Argv[1][0] > '9'))
  288.     usage();
  289.     Argc--;
  290.     Argv++;
  291.     return ntoi(Argv[0]);
  292. }
  293.  
  294. char        *
  295. argstring(char *def)
  296. {
  297.     if (Argc > 1) {
  298.     Argc--;
  299.     Argv++;
  300.     return Argv[0];
  301.     }
  302.     return def;
  303. }
  304.  
  305. int
  306. main(int argc, char **argv)
  307. {
  308.     struct MsgPort *port;
  309.     byte       *diskBlock;
  310.     long        unitNr;
  311.     int         i;
  312.     word        bps = MS_BPS,
  313.             spt = MS_SPT;
  314.     word        res,
  315.             nfats,
  316.             spf,
  317.             spc,
  318.             nsects,
  319.             ncylinders,
  320.             ndirs,
  321.             wholeDisk,
  322.             clearFat;
  323.  
  324.     Argc = argc;
  325.     Argv = argv;
  326.     Argv0 = argv[0];
  327.  
  328.     if (Argc < 2)
  329.     usage();
  330.  
  331.     Ask = argswitch("ASK");
  332.     Boot = argswitch("BOOT");
  333.     Quick = argswitch("QUICK");
  334.     unitNr = argnum();
  335.     Device = argstring("messydisk.device");
  336.  
  337.     signal(SIGINT, breakhandler);       /* Do not disturb */
  338.  
  339.     if (!(port = CreatePort(NULL, 0L))) {
  340.     puts("No memory for replyport");
  341.     goto abort1;
  342.     }
  343.     if (!(TDReq = (struct IOExtTD *)CreateExtIO(port, (long) sizeof (*TDReq)))) {
  344.     puts("No memory for I/O request");
  345.     goto abort2;
  346.     }
  347.     if (OpenDevice(Device, unitNr, (struct IORequest *)TDReq, 0L)) {
  348.     printf("Cannot OpenDevice %s\n", Device);
  349.     goto abort3;
  350.     }
  351.  
  352.     if (Ask) {
  353.     printf("Preparing to format disk in %s unit #%d.\n\n",
  354.         Device, (int) unitNr);
  355.     }
  356.     bps = input("Bytes per sector", bps);
  357.     spt = input("Sectors per track", spt);
  358.     TrackSize = bps * spt;
  359.     nsides = input("Number of sides", MS_NSIDES);
  360.     Track = input("Starting cylinder", 0);
  361.     Track *= nsides;
  362.     ncylinders = input("Number of cylinders", 80);
  363.     EndTrack = Track + nsides * ncylinders;
  364.  
  365.     if ((DiskTrack = AllocMem(TrackSize,
  366.             MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR)) == NULL) {
  367.     puts("No memory for track buffer");
  368.     goto abort4;
  369.     }
  370.     CopyMem((char *)BootBlock, DiskTrack, (long) sizeof (BootBlock));
  371.  
  372.     PutWord(DiskTrack + 0x0b, bps);
  373.     spc = SetByte(DiskTrack + 0x0d, "Sectors per cluster", MS_SPC);
  374.     res = SetWord(DiskTrack + 0x0e, "Bootsectors", MS_RES);
  375.     nfats = SetByte(DiskTrack + 0x10, "Number of FAT copies", MS_NFATS);
  376.     ndirs = SetWord(DiskTrack + 0x11, "Root directory entries", MS_NDIRS);
  377.     nsects = SetWord(DiskTrack + 0x13, "Total number of sectors", spt * ncylinders * nsides);
  378.     SetByte(DiskTrack + 0x15, "Media byte", 0xF9);
  379.     /*
  380.      * Suggest a minimum value for the number of FAT sectors.
  381.      * Here we assume all sectors are to be used for clusters, which is not
  382.      * really true, but simpler, and gives a conservative value. Besides,
  383.      * the number of available sectors also depends on the FAT size, so
  384.      * the whole calculation (if done correctly) would be recursive. In
  385.      * practice, it may occasionally suggest one sector too much.
  386.      */
  387.     {
  388.     long        nclusters;
  389.     long        nbytes;
  390.  
  391.     nclusters = MS_FIRSTCLUST + (nsects + spc - 1) / spc;
  392.     if (nclusters > 0xFF7) /* 16-bit FAT entries */
  393.         nbytes = nclusters * 2;
  394.     else              /* 12-bit FAT entries */
  395.         nbytes = (nclusters * 3 + 1) / 2;
  396.     spf = (nbytes + bps - 1) / bps;
  397.     /* Hack for floppies */
  398.     if (spf < MS_SPF)
  399.         spf = MS_SPF;
  400.  
  401.     }
  402.     spf = SetWord(DiskTrack + 0x16, "Sectors per FAT", spf);
  403.     PutWord(DiskTrack + 0x18, spt);
  404.     PutWord(DiskTrack + 0x1a, nsides);
  405.     SetWord(DiskTrack + 0x1c, "Number of hidden sectors", 0);
  406.  
  407.     wholeDisk = input("Format whole disk (enter 1)", 0);
  408.     if (!wholeDisk)
  409.     clearFat = input("Write how much then?\n"
  410.              " (enter 0 for just the bootblock)\n"
  411.              " (enter 1 for FAT and root directory as well)", 0);
  412.  
  413.     if (Ask) {
  414.     if (input("Are you sure? (enter 42)", 0) != 42)
  415.         goto abort5;
  416.     } else {
  417.     int ch;
  418.  
  419.     printf("Insert disk to be formatted in %s unit %d\nand press RETURN",
  420.         Device, unitNr);
  421.     fflush(stdout);
  422.     while ((ch = getchar()) != '\n' && ch != EOF)
  423.         ;
  424.     ch == '\n' || putchar('\n');
  425.     }
  426.  
  427.     /*
  428.      * Now use command line options to modify default values
  429.      */
  430.     if (!Ask)
  431.     wholeDisk = 1;
  432.     if (Quick) {
  433.     wholeDisk = 0;
  434.     clearFat = 1;
  435.     }
  436.     if (Boot) {
  437.     wholeDisk = 0;
  438.     clearFat = 0;
  439.     }
  440.  
  441.     chkabort();
  442.     if (Break)
  443.     goto abort5;
  444.  
  445.     if (!wholeDisk && !clearFat) {
  446.     puts("Writing bootblock only.");
  447.     TDReq->iotd_Req.io_Command = CMD_WRITE;
  448.     TDReq->iotd_Req.io_Data = (APTR) DiskTrack;
  449.     TDReq->iotd_Req.io_Length = sizeof (BootBlock);
  450.     TDReq->iotd_Req.io_Offset = 0;
  451.     DoIO((struct IORequest *)TDReq);
  452.     TDReq->iotd_Req.io_Command = CMD_UPDATE;
  453.     DoIO((struct IORequest *)TDReq);
  454.  
  455.     goto done;
  456.     }
  457.  
  458.     /* Go to first FAT */
  459.     diskBlock = MaybeWrite(DiskTrack + bps * res);
  460.     for (i = 0; i < nfats; i++) {
  461.     diskBlock[0] = 0xF9;
  462.     diskBlock[1] = 0xFF;
  463.     diskBlock[2] = 0xFF;
  464.     diskBlock = MaybeWrite(diskBlock + bps * spf);  /* Next FAT */
  465.     }
  466.  
  467.     /* Clear entire directory */
  468.     diskBlock = MaybeWrite(diskBlock + ndirs * MS_DIRENTSIZE);
  469.     MaybeWrite(DiskTrack + TrackSize);  /* Force a write */
  470.  
  471.     if (wholeDisk) {
  472.     while (Track < EndTrack) {
  473.         MaybeWrite(DiskTrack + TrackSize);  /* Write an empty track */
  474.         if (Break)
  475.         break;
  476.     }
  477.     }
  478.  
  479. done:
  480.     TDReq->iotd_Req.io_Command = TD_MOTOR;
  481.     TDReq->iotd_Req.io_Length = 0;
  482.     DoIO((struct IORequest *)TDReq);
  483.  
  484.     printf("\n\nNow remove the disk from the drive (or use DiskChange).\n");
  485.  
  486. abort5:
  487.     FreeMem(DiskTrack, TrackSize);
  488. abort4:
  489.     CloseDevice((struct IORequest *)TDReq);
  490. abort3:
  491.     DeleteExtIO((struct IORequest *)TDReq);
  492. abort2:
  493.     DeletePort(port);
  494. abort1:;
  495.  
  496.     signal(SIGINT, SIG_DFL);
  497.  
  498.     return 0;
  499. }
  500.